#include "TokenIntExp.h"
#include "Value.h"
#include "VarTable.h"
#include "Error.h"
#include <string>
#include <cassert>
#include <sstream>
using namespace std;
void TokenInt::run(bool enabled /*= true*/)
{
	if (toParse == "")
		throw Error("Int expected but not found.");
	istringstream sin(toParse);
	int r;
	if (sin >> r)
	{
		result = new ValueInt(r);
		string word;
		sin >> word;
		if (word != "")
			throw Error("Unexpected \"" + word + "\" after literal-int.");
	}
	else
	{
		VarTable* t = VarTable::getInstance();
		ValueInt* p = t -> get(toParse);
		if (p == NULL)
			throw Error("Undefined variable: " + t -> extractVarname(toParse));
		result = new ValueInt(*p); //copy constructor
	}
}
void TokenIntMul::run(bool enabled /*= true*/)
{
	if (toParse == "")
		throw Error("Int expression (term) expected but not found.");
	int opp, opmul, opdiv; // operator position
	char opc; // operator charater
	opmul = toParse.rfind('*');
	opdiv = toParse.rfind('/');
	if (opmul == string::npos && opdiv == string::npos)
	{
		opc = 'N'; //None
		opp = -1;
	}
	else if (opdiv == string::npos || opmul != string::npos && opmul > opdiv)
	{
		opc = '*';
		opp = opmul;
	}
	else
	{
		opc = '/';
		opp = opdiv;
	}
	TokenInt* rhs = new TokenInt(toParse.substr(opp+1, toParse.size()-1-opp));
	ValueInt rhsr = rhs -> getResult();
	if (opc == 'N') {result = new ValueInt(rhsr);return;}
	TokenIntMul* lhs = new TokenIntMul(toParse.substr(0, opp));
	ValueInt lhsr = lhs -> getResult();
	if (opc == '*')
		result = new ValueInt(lhsr.mul(rhsr)); // copy constructor
	else
		result = new ValueInt(lhsr.div(rhsr));
}
void TokenIntExp::run(bool enabled /*= true*/)
{
	if (toParse == "")
		throw Error("Int expression expected but not found.");
	if (toParse[0] == '+' || toParse[0] == '-')
		toParse = "0" + toParse;
	int opp, opadd, opsub; // operator position
	char opc; // operator charater
	opadd = toParse.rfind('+');
	opsub = toParse.rfind('-');
	if (opadd == string::npos && opsub == string::npos)
	{
		opc = 'N'; //None
		opp = -1;
	}
	else if (opsub == string::npos || opadd != string::npos && opadd > opsub)
	{
		opc = '+';
		opp = opadd;
	}
	else
	{
		opc = '-';
		opp = opsub;
	}
	TokenIntMul* rhs = new TokenIntMul(toParse.substr(opp+1, toParse.size()-1-opp));
	ValueInt rhsr = rhs -> getResult();
	if (opc == 'N') {result = new ValueInt(rhsr);return;}
	TokenIntExp* lhs = new TokenIntExp(toParse.substr(0, opp));
	ValueInt lhsr = lhs -> getResult();
	if (opc == '+')
		result = new ValueInt(lhsr.add(rhsr)); // copy constructor
	else
		result = new ValueInt(lhsr.sub(rhsr));
}

